import ccclass = cc._decorator.ccclass;
import property = cc._decorator.property;
import Timer from "../game/timer";
import Hero from "../hero";
import AiScript from "../ai-script";
import GameBoard from "../game/gameboard";
import executionOrder = cc._decorator.executionOrder;
import BeKilledBoard from "../result/beKilledBoard";

@ccclass
@executionOrder(10)
export default class UpdateController extends cc.Component {

  private fixedTime = 0.02;
  @property(Timer)
  private timer: Timer = null;
  @property(cc.Node)
  private players: cc.Node = null;
  @property(GameBoard)
  private gameBoard: GameBoard = null;
  @property(BeKilledBoard)
  private beKillBoard: BeKilledBoard = null;

  private count = 0;

  start() {
    this.count = 0;
  }

  private time = 0;

  private tickMap = new Map<number, Array<TickFunc>>();
  private targetMap = new Map<any, Array<TickFunc>>()

  update(dt) {
    this.time += dt;
    if (this.time > this.fixedTime) {
      const count = Math.floor(this.time / this.fixedTime);
      for (let i = 0; i < count; i++) {
        this.updateFixedFrame();
      }

      this.time = this.time % this.fixedTime;
    }
  }

  updateFixedFrame() {
    this.timer.updateFixedFrame(this.fixedTime);
    this.players.children.forEach(player => {
      player.getComponent(Hero).updateFixedFrame(this.fixedTime);
      const ai = player.getComponent(AiScript)
      if (ai) {
        ai.updateFixedFrame(this.fixedTime)
      }
    });
    this.gameBoard.updateFixedFrame(this.fixedTime)
    this.beKillBoard.updateFixedFrame(this.fixedTime)

    //执行碰撞检测
    const manager = cc.director.getCollisionManager()
    manager.enabled = true;
    (manager as any).update(this.fixedTime);
    manager.enabled = false;

    //调用
    this.callTickFunc();

    this.count++;
  }

  callTickFunc() {
    const callbacks = this.tickMap.get(this.count);
    if (callbacks) {
      callbacks.forEach(callback => {
        if (callback.enabled) {
          callback.func()
        }
      })
      this.tickMap.delete(this.count);
    }
  }

  addTickFunc(func: Function, countAfter: number, target?: any) {
    const callbacks = this.getIfAbsence(this.tickMap, this.count + countAfter, []);
    const tickFuncRecord = this.getIfAbsence(this.targetMap, target, [])

    const tickFunc = {func, target, enabled: true}
    callbacks.push(tickFunc)
    tickFuncRecord.push(tickFunc);
  }

  removeAllTickFunc(target: any) {
    const tickFuncRecord: Array<TickFunc> = this.getIfAbsence(this.targetMap, target, [])
    tickFuncRecord.forEach(value => {
      value.enabled = false;
    })
    this.targetMap.delete(target)
  }

  getIfAbsence(map: Map, key: any, defaultValue: any) {
    const v = map.get(key)
    if (v) {
      return v
    } else {
      map.set(key, defaultValue)
      return defaultValue;
    }
  }
}

interface TickFunc {
  target: any,
  func: Function,
  enabled: boolean,
}